Detectable auto-repeat - make a repeating key generate
authorOwen Taylor <otaylor@redhat.com>
Sat, 3 Mar 2001 21:34:19 +0000 (21:34 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Sat, 3 Mar 2001 21:34:19 +0000 (21:34 +0000)
Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>

* gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c
  gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:

Detectable auto-repeat - make a repeating key generate
press/press/press/release instead of press/release pairs.

If we have Xkb and XkbSetDectableAutoRepeat supports
that, we do it that way. Otherwise, when we get
a release event, we check ahead with XPending to see
if the next key is a KeyPress with the same keycode
and timestamp. (Not 100% reliable, but pretty close.)

Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>

   * gtk/gtkmain.c (gtk_propagate_event): Only do special
        special key-press grab handling for widgets within
        GtkWindows. Otherwise, fall through to normal case.

        This prevents key events being sent twice to GtkInvisible
        widgets, which can cause all sorts of mischief.

12 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/x11/gdkevents-x11.c
gdk/x11/gdkkeys-x11.c
gdk/x11/gdkmain-x11.c
gdk/x11/gdkprivate-x11.h
gtk/gtkmain.c

index 9c25cb17249a8106a557a16baa0686f3e8e6cf88..4274d7735203b13a9aa3a52579a11c2219928959 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c 
+         gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:
+
+       Detectable auto-repeat - make a repeating key generate
+       press/press/press/release instead of press/release pairs.
+
+       If we have Xkb and XkbSetDectableAutoRepeat supports
+       that, we do it that way. Otherwise, when we get
+       a release event, we check ahead with XPending to see
+       if the next key is a KeyPress with the same keycode
+       and timestamp. (Not 100% reliable, but pretty close.)
+         
+Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>
+       
+       * gtk/gtkmain.c (gtk_propagate_event): Only do special
+        special key-press grab handling for widgets within
+        GtkWindows. Otherwise, fall through to normal case.
+        This prevents key events being sent twice to GtkInvisible
+        widgets, which can cause all sorts of mischief.
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor@redhat.com>
+       * gtk/gtkmain.c (gtk_propagate_event): When a grab
+       widget is in effect, give the grab widget a first
+       crack at KEY_PRESS/RELEASE events. (#424)
 Sat Mar  3 15:39:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking
index 9c25cb17249a8106a557a16baa0686f3e8e6cf88..4274d7735203b13a9aa3a52579a11c2219928959 100644 (file)
@@ -1,3 +1,32 @@
+Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c 
+         gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:
+
+       Detectable auto-repeat - make a repeating key generate
+       press/press/press/release instead of press/release pairs.
+
+       If we have Xkb and XkbSetDectableAutoRepeat supports
+       that, we do it that way. Otherwise, when we get
+       a release event, we check ahead with XPending to see
+       if the next key is a KeyPress with the same keycode
+       and timestamp. (Not 100% reliable, but pretty close.)
+         
+Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>
+       
+       * gtk/gtkmain.c (gtk_propagate_event): Only do special
+        special key-press grab handling for widgets within
+        GtkWindows. Otherwise, fall through to normal case.
+        This prevents key events being sent twice to GtkInvisible
+        widgets, which can cause all sorts of mischief.
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor@redhat.com>
+       * gtk/gtkmain.c (gtk_propagate_event): When a grab
+       widget is in effect, give the grab widget a first
+       crack at KEY_PRESS/RELEASE events. (#424)
 Sat Mar  3 15:39:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking
index 9c25cb17249a8106a557a16baa0686f3e8e6cf88..4274d7735203b13a9aa3a52579a11c2219928959 100644 (file)
@@ -1,3 +1,32 @@
+Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c 
+         gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:
+
+       Detectable auto-repeat - make a repeating key generate
+       press/press/press/release instead of press/release pairs.
+
+       If we have Xkb and XkbSetDectableAutoRepeat supports
+       that, we do it that way. Otherwise, when we get
+       a release event, we check ahead with XPending to see
+       if the next key is a KeyPress with the same keycode
+       and timestamp. (Not 100% reliable, but pretty close.)
+         
+Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>
+       
+       * gtk/gtkmain.c (gtk_propagate_event): Only do special
+        special key-press grab handling for widgets within
+        GtkWindows. Otherwise, fall through to normal case.
+        This prevents key events being sent twice to GtkInvisible
+        widgets, which can cause all sorts of mischief.
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor@redhat.com>
+       * gtk/gtkmain.c (gtk_propagate_event): When a grab
+       widget is in effect, give the grab widget a first
+       crack at KEY_PRESS/RELEASE events. (#424)
 Sat Mar  3 15:39:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking
index 9c25cb17249a8106a557a16baa0686f3e8e6cf88..4274d7735203b13a9aa3a52579a11c2219928959 100644 (file)
@@ -1,3 +1,32 @@
+Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c 
+         gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:
+
+       Detectable auto-repeat - make a repeating key generate
+       press/press/press/release instead of press/release pairs.
+
+       If we have Xkb and XkbSetDectableAutoRepeat supports
+       that, we do it that way. Otherwise, when we get
+       a release event, we check ahead with XPending to see
+       if the next key is a KeyPress with the same keycode
+       and timestamp. (Not 100% reliable, but pretty close.)
+         
+Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>
+       
+       * gtk/gtkmain.c (gtk_propagate_event): Only do special
+        special key-press grab handling for widgets within
+        GtkWindows. Otherwise, fall through to normal case.
+        This prevents key events being sent twice to GtkInvisible
+        widgets, which can cause all sorts of mischief.
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor@redhat.com>
+       * gtk/gtkmain.c (gtk_propagate_event): When a grab
+       widget is in effect, give the grab widget a first
+       crack at KEY_PRESS/RELEASE events. (#424)
 Sat Mar  3 15:39:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking
index 9c25cb17249a8106a557a16baa0686f3e8e6cf88..4274d7735203b13a9aa3a52579a11c2219928959 100644 (file)
@@ -1,3 +1,32 @@
+Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c 
+         gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:
+
+       Detectable auto-repeat - make a repeating key generate
+       press/press/press/release instead of press/release pairs.
+
+       If we have Xkb and XkbSetDectableAutoRepeat supports
+       that, we do it that way. Otherwise, when we get
+       a release event, we check ahead with XPending to see
+       if the next key is a KeyPress with the same keycode
+       and timestamp. (Not 100% reliable, but pretty close.)
+         
+Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>
+       
+       * gtk/gtkmain.c (gtk_propagate_event): Only do special
+        special key-press grab handling for widgets within
+        GtkWindows. Otherwise, fall through to normal case.
+        This prevents key events being sent twice to GtkInvisible
+        widgets, which can cause all sorts of mischief.
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor@redhat.com>
+       * gtk/gtkmain.c (gtk_propagate_event): When a grab
+       widget is in effect, give the grab widget a first
+       crack at KEY_PRESS/RELEASE events. (#424)
 Sat Mar  3 15:39:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking
index 9c25cb17249a8106a557a16baa0686f3e8e6cf88..4274d7735203b13a9aa3a52579a11c2219928959 100644 (file)
@@ -1,3 +1,32 @@
+Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c 
+         gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:
+
+       Detectable auto-repeat - make a repeating key generate
+       press/press/press/release instead of press/release pairs.
+
+       If we have Xkb and XkbSetDectableAutoRepeat supports
+       that, we do it that way. Otherwise, when we get
+       a release event, we check ahead with XPending to see
+       if the next key is a KeyPress with the same keycode
+       and timestamp. (Not 100% reliable, but pretty close.)
+         
+Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>
+       
+       * gtk/gtkmain.c (gtk_propagate_event): Only do special
+        special key-press grab handling for widgets within
+        GtkWindows. Otherwise, fall through to normal case.
+        This prevents key events being sent twice to GtkInvisible
+        widgets, which can cause all sorts of mischief.
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor@redhat.com>
+       * gtk/gtkmain.c (gtk_propagate_event): When a grab
+       widget is in effect, give the grab widget a first
+       crack at KEY_PRESS/RELEASE events. (#424)
 Sat Mar  3 15:39:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking
index 9c25cb17249a8106a557a16baa0686f3e8e6cf88..4274d7735203b13a9aa3a52579a11c2219928959 100644 (file)
@@ -1,3 +1,32 @@
+Sat Mar  3 16:26:33 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c 
+         gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c:
+
+       Detectable auto-repeat - make a repeating key generate
+       press/press/press/release instead of press/release pairs.
+
+       If we have Xkb and XkbSetDectableAutoRepeat supports
+       that, we do it that way. Otherwise, when we get
+       a release event, we check ahead with XPending to see
+       if the next key is a KeyPress with the same keycode
+       and timestamp. (Not 100% reliable, but pretty close.)
+         
+Tue Feb 27 02:16:14 2001  Owen Taylor  <otaylor@redhat.com>
+       
+       * gtk/gtkmain.c (gtk_propagate_event): Only do special
+        special key-press grab handling for widgets within
+        GtkWindows. Otherwise, fall through to normal case.
+        This prevents key events being sent twice to GtkInvisible
+        widgets, which can cause all sorts of mischief.
+Fri Feb  2 13:20:12 2001  Owen Taylor  <otaylor@redhat.com>
+       * gtk/gtkmain.c (gtk_propagate_event): When a grab
+       widget is in effect, give the grab widget a first
+       crack at KEY_PRESS/RELEASE events. (#424)
 Sat Mar  3 15:39:49 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking
index 0f590774c7d7dbf44c423faec814abbdfa390908..87ed39295295bfcb93c9c16dea20f6c9a9f85be2 100644 (file)
@@ -530,7 +530,7 @@ gdk_event_translate (GdkEvent *event,
     case KeyPress:
       /* Lookup the string corresponding to the given keysym.
        */
-      
+
 #ifdef USE_XIM
       if (buf_len == 0) 
        {
@@ -613,6 +613,24 @@ gdk_event_translate (GdkEvent *event,
     case KeyRelease:
       /* Lookup the string corresponding to the given keysym.
        */
+
+      /* Emulate detectable auto-repeat by checking to see
+       * if the next event is a key press with the same
+       * keycode and timestamp, and if so, ignoring the event.
+       */
+
+      if (!_gdk_have_xkb_autorepeat && XPending (gdk_display))
+       {
+         XEvent next_event;
+
+         XPeekEvent (gdk_display, &next_event);
+
+         if (next_event.type == KeyPress &&
+             next_event.xkey.keycode == xevent->xkey.keycode &&
+             next_event.xkey.time == xevent->xkey.time)
+           break;
+       }
+      
 #ifdef USE_XIM
       if (buf_len == 0) 
        {
index dc807d849429534a6ec03f2d7338160435f792ce..8d8876a1ad8aaec94678d1244b8a1b975791fe5d 100644 (file)
@@ -82,6 +82,12 @@ get_xkb (void)
 }
 #endif /* HAVE_XKB */
 
+/* Whether we were able to turn on detectable-autorepeat using
+ * XkbSetDetectableAutorepeat. If FALSE, we'll fall back
+ * to checking the next event with XPending().
+ */
+gboolean _gdk_have_xkb_autorepeat = FALSE;
+
 static KeySym* keymap = NULL;
 static gint keysyms_per_keycode = 0;
 static XModifierKeymap* mod_keymap = NULL;
index ff6fa309cc83eee87f4b21c9f443b87723374bc1..76a1ab19153c858922a080814cf6ffe57e67622a 100644 (file)
@@ -214,12 +214,23 @@ _gdk_windowing_init_check (int argc, char **argv)
         if (XkbQueryExtension (gdk_display, NULL, NULL, NULL,
                                &xkb_major, &xkb_minor))
           {
+           Bool detectable_autorepeat_supported;
+           
             _gdk_use_xkb = TRUE;
 
             XkbSelectEvents (gdk_display,
                              XkbUseCoreKbd,
                              XkbMapNotifyMask,
                              XkbMapNotifyMask);
+
+           XkbSetDetectableAutoRepeat (gdk_display,
+                                       True,
+                                       &detectable_autorepeat_supported);
+
+           GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
+                                      detectable_autorepeat_supported ? "supported" : "not supported"));
+           
+           _gdk_have_xkb_autorepeat = detectable_autorepeat_supported;
           }
       }
   }
index 0d03177fd376bfa49ab3f5ed58d1849c91d4f969..24f7075c40ac30f8a21ac302a6167f0f94806364 100644 (file)
@@ -113,8 +113,15 @@ extern GdkWindow *gdk_xim_window;          /* currently using Window */
 
 /* Used to detect not-up-to-date keymap */
 extern guint _gdk_keymap_serial;
+
 #ifdef HAVE_XKB
 extern gboolean _gdk_use_xkb;
 #endif
 
+/* Whether we were able to turn on detectable-autorepeat using
+ * XkbSetDetectableAutorepeat. If FALSE, we'll fall back
+ * to checking the next event with XPending().
+ */
+extern gboolean _gdk_have_xkb_autorepeat;
+
 #endif /* __GDK_PRIVATE_X11_H__ */
index 0689427e5ae6c0e96776c2e86aa398c5e33dac5f..f8801cc1b8be8a847b8d67ae8775249b0ed2624d 100644 (file)
@@ -1509,6 +1509,8 @@ gtk_propagate_event (GtkWidget *widget,
   
   handled_event = FALSE;
 
+  gtk_widget_ref (widget);
+      
   if ((event->type == GDK_KEY_PRESS) ||
       (event->type == GDK_KEY_RELEASE))
     {
@@ -1520,29 +1522,53 @@ gtk_propagate_event (GtkWidget *widget,
       GtkWidget *window;
 
       window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
-      if (window)
-        {
-         if (GTK_WIDGET_IS_SENSITIVE (window))
-           gtk_widget_event (window, event);
 
-          handled_event = TRUE; /* don't send to widget */
-        }
+      if (window)
+       {
+         /* If there is a grab within the window, give the grab widget
+          * a first crack at the key event
+          */
+         if (widget != window && GTK_WIDGET_HAS_GRAB (widget))
+           handled_event = gtk_widget_event (widget, event);
+         
+         if (!handled_event)
+           {
+             window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+             if (window)
+               {
+                 if (GTK_WIDGET_IS_SENSITIVE (window))
+                   gtk_widget_event (window, event);
+               }
+           }
+                 
+         handled_event = TRUE; /* don't send to widget */
+       }
     }
   
   /* Other events get propagated up the widget tree
    *  so that parents can see the button and motion
    *  events of the children.
    */
-  while (!handled_event && widget)
+  if (!handled_event)
     {
-      GtkWidget *tmp;
+      while (TRUE)
+       {
+         GtkWidget *tmp;
+         
+         handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event);
+         tmp = widget->parent;
+         gtk_widget_unref (widget);
 
-      gtk_widget_ref (widget);
-      handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event);
-      tmp = widget->parent;
-      gtk_widget_unref (widget);
-      widget  = tmp;
+         widget = tmp;
+         
+         if (!handled_event && widget)
+           gtk_widget_ref (widget);
+         else
+           break;
+       }
     }
+  else
+    gtk_widget_unref (widget);
 }
 
 #if 0